package divideAndConquer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.StringTokenizer;

/*

设有2**k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表：
① 每个选手必须与其他 n-1 个选手各赛一次;
② 每个选手一天只能赛一次；
③ 循环赛一共进行 n-1 天;

0 1
1 0

0 1 2 3
1 0 3 2
2 3 0 1
3 2 1 0

0 1 2 3 4 5 6 7
1 0 3 2 5 4 7 6
2 3 0 1 6 7 4 5
3 2 1 0 7 6 5 4
4 5 6 7 0 1 2 3
5 4 7 6 1 0 3 2
6 7 4 5 2 3 0 1
7 6 5 4 3 2 1 0

 */
public class CircularRaceSchedule {
    
    static InOut2 io = new InOut2();
    
    int n, i;
    int[][] schedule;
    public CircularRaceSchedule() {
        n = (int) Math.pow(2, io.nextInt());
        schedule = new int[n][n];
        divide(0, 0, n);
    }
    public void divide(int startRow, int startColumn, int n) {
        // printSchedule();
        io.out.println();
        int mid = n/2;
        if (n == 2) {
            schedule[startRow][startColumn] = i++;
            schedule[startRow][startColumn+1] = i++;
        } else {
            divide(startRow, startColumn, mid);
            divide(startRow, startColumn + mid, mid);
        }
        copy(startRow, startColumn, mid, true);
        copy(startRow, startColumn+mid, mid, false);
    }

    private void copy(int startRow, int startColumn, int size, boolean left) {
        // TODO Auto-generated method stub
        for (int j = startRow; j < startRow + size; j++) {
            for (int k = startColumn; k < startColumn + size; k++) {
                if (left) {
                    schedule[j+size][k+size] = schedule[j][k];
                } else {
                    schedule[j+size][k-size] = schedule[j][k];
                }
            }
        }
        io.out.println();
    }
    public void printSchedule() {
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                io.out.print(schedule[j][k] + "\t");
            }
            io.out.println();
            io.out.println();
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        CircularRaceSchedule c = new CircularRaceSchedule();
        c.printSchedule();
        io.out.flush();
    }

}
class InOut2 {
    BufferedReader br;
    StringTokenizer tok;
    PrintWriter out;
    InOut2() {
        br = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(new OutputStreamWriter(System.out));
    }
    public boolean hasNext() {
        while (tok == null || !tok.hasMoreElements()) {
            try {
                tok = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                return false;
            }
        }
        return true;
    }
    public String next() {
        if (hasNext()) {
            return tok.nextToken();
        }
        return null;
    }
    public int nextInt() {
        return Integer.parseInt(next());
    }
}
